/**
 * Copyright (C) 2017 - 2020 https://github.com/joewee
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bifrost.wechat.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.protocol.HTTP;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;

/**
 *重写获取token
 *
 *@author joewee
 *@version 1.0.0
 *@Date 2018/3/13 17:15
 */
public class CbestWxMpService extends WxMpServiceImpl {
    private String CBEST_TOKEN_URL="http://weixin.e-cbest.com/mall/wechat/accessToken";
    private String accessKey="";
    public CbestWxMpService(String  key) {
        new CbestWxMpService(key,null);
    }
    public CbestWxMpService(String  key,String tokenUrl) {
        super();
        if (StringUtils.isNotBlank(key)) {
            this.accessKey=key;
        }
        if(StringUtils.isNotBlank(tokenUrl)){
            this.CBEST_TOKEN_URL=tokenUrl;
        }
    }
    @Override
    public String getAccessToken(boolean forceRefresh) throws WxErrorException{
        Lock lock = this.getWxMpConfigStorage().getAccessTokenLock();
        try {
            lock.lock();
            if (this.getWxMpConfigStorage().isAccessTokenExpired() || forceRefresh) {
                try {
                    HttpPost httpPost = new HttpPost(CBEST_TOKEN_URL);
                    if (this.getRequestHttpProxy() != null) {
                        RequestConfig config = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
                        httpPost.setConfig(config);
                    }
                    httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json");
                    httpPost.setHeader("Signature",DigestUtils.md5Hex(accessKey.getBytes()).toUpperCase());
                    Map jsonMap = new HashMap();
                    jsonMap.put("appid",this.getWxMpConfigStorage().getAppId());
                    //若刷新为false则验证accesstoken是否过期
                    jsonMap.put("forceRefresh",forceRefresh==false?this.getWxMpConfigStorage().isAccessTokenExpired():true);
                    StringEntity entity = new StringEntity(JSON.toJSONString(jsonMap),"UTF-8");
                    entity.setContentEncoding("UTF-8");
                    entity.setContentType("application/json");
                    httpPost.setEntity(entity);
                    try {
                        CloseableHttpResponse response = this.getRequestHttpClient().execute(httpPost);
                        Throwable var6 = null;
                        try {
                            String resultContent = (new BasicResponseHandler()).handleResponse(response);
                           JSONObject result = JSON.parseObject(resultContent);
                            if (!"0".equals(result.getString("errCode"))) {
                                throw new RuntimeException(result.getString("errMessage"));
                            }
                            Map map = new HashMap();
                            map.put("access_token",result.getJSONObject("data").getString("access_token"));
                            map.put("expires_in",result.getJSONObject("data").getLongValue("expiresin"));
                            WxAccessToken accessToken = WxAccessToken.fromJson(JSON.toJSONString(map));
                            this.getWxMpConfigStorage().updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn()==0?7000:accessToken.getExpiresIn());
                        } finally {
                            httpPost.releaseConnection();
                        }
                    } finally {
                        httpPost.releaseConnection();
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        } finally {
            lock.unlock();
        }
        return this.getWxMpConfigStorage().getAccessToken();
    }
}
